package com.example.demo.controller;

import com.example.demo.dto.*;
import com.example.demo.mode.PrintFile;
import com.example.demo.mode.PrintFilesSub;
import com.example.demo.service.PrintFileService;
import com.example.demo.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
 * @author 21024
 */
@Controller
@CrossOrigin(origins = "*")
@ResponseBody
@RequestMapping("/print")
@Slf4j
public class PrintCollect {
    private final PrintFileService printFileService;
    @Value("${file.upload.dir}")
    private String uploadDir;

    @Autowired
    public PrintCollect(PrintFileService printFileService) {
        this.printFileService = printFileService;
    }

    @GetMapping("/list")
    public List<PrintFileListDto> printFileList() {
        return printFileService.printFileList();
    }

    @GetMapping("/find/{partNumber}")
    public int findByPartNumber(@PathVariable String partNumber) {
        return printFileService.selectPartNumber(partNumber);
    }

    @GetMapping("/{partNumber}")
    public PrintFileDto findPartNumber(@PathVariable String partNumber) {
        return printFileService.selectByPartNumber(partNumber);
    }

    @PutMapping("/{condition}")
    public List<PrintFileListDto> query(@PathVariable String condition) {
        return printFileService.findPrintFileList(condition);
    }

    @GetMapping("/downloadList/{partNumber}")
    public List<DownloadPrintFileListDto> downloadPrintFileList(@PathVariable String partNumber) {
        return printFileService.downloadPrintFileList(partNumber);
    }

    @PutMapping("/download/history")
    public void getDownloadFile(@RequestBody PrintDownloadUserDto dto, HttpServletRequest request) {
        log.info("提交打印文件下载请求,文件名:{},IP地址:{}", dto.getFileName(), IpUtils.getClientIp(request));
        printFileService.getDownloadFile(dto, IpUtils.getClientIp(request));
    }

    @PostMapping("/update")
    public Boolean update(@RequestPart(value = "data") PrintFile printFile, @RequestPart(value = "file", required = false) List<MultipartFile> multipartFiles, HttpServletRequest request) {
        log.info("雕刻文件更新请求,品号:{},更新版本号:{}", printFile.getPartNumber(), printFile.getVersion());
        StringBuilder fileNameListBuilder = new StringBuilder();
        if (multipartFiles != null) {
            for (MultipartFile multipartFile : multipartFiles) {
                log.info("雕刻文件件更新,新文件名:{}", multipartFile.getOriginalFilename());
                String fileName = multipartFile.getOriginalFilename();
                fileNameListBuilder.append(fileName).append(";");
                String[] fileNameArray = parseFileName(fileName);
                /*
                  保留版本回溯
                */
//                if (Boolean.FALSE.equals(printFileService.updatePrintFilesSub(fileName, fileNameArray[0], fileNameArray[1]))) {
//                    printFileService.insertPrintFilesSub(new PrintFilesSub(printFile.getFileId(), fileNameArray[1], fileName, fileNameArray[0]));
//                }
                printFileService.insertPrintFilesSub(new PrintFilesSub(printFile.getFileId(), fileNameArray[1], fileName, fileNameArray[0]));
                Path targetDir = Paths.get(uploadDir);

                try {
                    Files.createDirectories(targetDir);

                    if (fileName.contains("..")) {
                        log.debug("非法文件名: {}", fileName);
                        throw new SecurityException("非法文件名: " + fileName);
                    }
                    Path targetPath = targetDir.resolve(fileName);
                    try (InputStream is = multipartFile.getInputStream(); OutputStream os = new BufferedOutputStream(Files.newOutputStream(targetPath))) {

                        byte[] buffer = new byte[8192];
                        int bytesRead;
                        while ((bytesRead = is.read(buffer)) != -1) {
                            os.write(buffer, 0, bytesRead);
                        }

                        log.info("文件保存成功: {}", fileName);
                    } catch (IOException e) {
                        Files.deleteIfExists(targetPath);
                        log.error("文件保存失败: {}", fileName);
                        throw new RuntimeException("文件保存失败: " + fileName, e);
                    }
                } catch (IOException e) {
                    log.error("创建目录失败: {}", uploadDir);
                    throw new RuntimeException("创建目录失败: " + uploadDir, e);
                }

            }
        }
        return printFileService.update(printFile, IpUtils.getClientIp(request), fileNameListBuilder);
    }

    @PostMapping("/insert")
    public Boolean insert(@RequestPart(value = "data") NewPrintFileDto printFile, @RequestPart(value = "file") List<MultipartFile> multipartFiles, HttpServletRequest request) {
        log.info("新建雕刻文件插入请求,品号:{}", printFile.getPartNumber());
        StringBuilder fileNameListBuilder = new StringBuilder();
        if (multipartFiles != null) {
            for (MultipartFile multipartFile : multipartFiles) {
                String fileName = multipartFile.getOriginalFilename();
                fileNameListBuilder.append(fileName).append(";");
                Path targetDir = Paths.get(uploadDir);

                try {
                    Files.createDirectories(targetDir);

                    if (fileName.contains("..")) {
                        log.debug("非法文件名: {}", fileName);
                        throw new SecurityException("非法文件名: " + fileName);
                    }
                    Path targetPath = targetDir.resolve(fileName);
                    try (InputStream is = multipartFile.getInputStream(); OutputStream os = new BufferedOutputStream(Files.newOutputStream(targetPath))) {

                        byte[] buffer = new byte[8192];
                        int bytesRead;
                        while ((bytesRead = is.read(buffer)) != -1) {
                            os.write(buffer, 0, bytesRead);
                        }

                        log.info("文件保存成功: {}", fileName);
                    } catch (IOException e) {
                        Files.deleteIfExists(targetPath);
                        log.error("文件保存失败: {}", fileName);
                        throw new RuntimeException("文件保存失败: " + fileName, e);
                    }
                } catch (IOException e) {
                    log.error("创建目录失败: {}", uploadDir);
                    throw new RuntimeException("创建目录失败: " + uploadDir, e);
                }
            }
        }
        return printFileService.insert(printFile, IpUtils.getClientIp(request), fileNameListBuilder);
    }

    private String[] parseFileName(String fileName) {
        if (fileName.contains(".")) {
            fileName = fileName.substring(0, fileName.lastIndexOf("."));
        }

        String[] parts = fileName.split("_");

        if (parts.length >= 4 && "DK".equals(parts[0])) {
            String partNumber = parts[1];
            String subPartName = parts[2];
            String version = parts[3];

            if (parts.length > 4) {
                StringBuilder subPartBuilder = new StringBuilder(subPartName);
                int versionIndex = 3;
                while (versionIndex < parts.length - 1) {
                    subPartBuilder.append("_").append(parts[versionIndex]);
                    versionIndex++;
                }
                subPartName = subPartBuilder.toString();
                version = parts[parts.length - 1];
            }

            return new String[]{partNumber, subPartName, version};
        } else {
            throw new IllegalArgumentException("文件名格式不正确: " + fileName);
        }
    }
}

